/**
 * @file om_order.h
 * @brief 订单管理器订单相关数据结构的定义
 * 
 * @details 该文件定义了订单管理器（Order Manager）中使用的数据结构，
 * 包括订单状态（OMOrderState）和订单结构（OMOrder）。
 * 这些数据结构用于表示和管理交易策略发出的订单。
 * 
 * @author 原作者
 * @date 2023
 */

#pragma once

#include <array>
#include <sstream>
#include "common/types.h"

using namespace Common;

/**
 * @namespace Trading
 * @brief 交易相关的命名空间
 * 
 * @details 包含交易系统的核心组件，如订单、订单管理器、交易引擎等。
 */
namespace Trading {
  /**
   * @enum OMOrderState
   * @brief 订单管理器中的订单状态枚举
   * 
   * @details 表示订单管理器中订单结构的类型或状态。
   * 订单在其生命周期内会经历不同的状态，从创建到最终完成或取消。
   */
  enum class OMOrderState : int8_t {
    /**
     * @brief 无效状态
     * 
     * @details 表示订单处于无效状态，通常是初始化值或表示错误。
     */
    INVALID = 0,
    
    /**
     * @brief 等待新建状态
     * 
     * @details 表示订单已被创建并提交给交易所，但尚未收到确认。
     * 这是订单创建后的第一个状态。
     */
    PENDING_NEW = 1,
    
    /**
     * @brief 活跃状态
     * 
     * @details 表示订单已被交易所确认并在市场上活跃。
     * 这意味着订单已经进入交易所的订单簿，可以被成交。
     */
    LIVE = 2,
    
    /**
     * @brief 等待取消状态
     * 
     * @details 表示已发出取消订单的请求，但尚未收到交易所的取消确认。
     * 订单仍然可能在市场上活跃。
     */
    PENDING_CANCEL = 3,
    
    /**
     * @brief 死亡状态
     * 
     * @details 表示订单已经结束，可能是因为完全成交、被取消或被拒绝。
     * 这是订单的最终状态，不会再发生变化。
     */
    DEAD = 4
  };

  /**
   * @brief 将订单状态枚举转换为字符串
   * 
   * @details 将 OMOrderState 枚举值转换为其对应的字符串表示。
   * 主要用于调试、日志记录和错误报告。
   * 
   * @param side 要转换的订单状态枚举值
   * @return 订单状态的字符串表示，如果状态不识别则返回 "UNKNOWN"
   */
  inline auto OMOrderStateToString(OMOrderState side) -> std::string {
    switch (side) {
      case OMOrderState::PENDING_NEW:
        return "PENDING_NEW";
      case OMOrderState::LIVE:
        return "LIVE";
      case OMOrderState::PENDING_CANCEL:
        return "PENDING_CANCEL";
      case OMOrderState::DEAD:
        return "DEAD";
      case OMOrderState::INVALID:
        return "INVALID";
    }

    return "UNKNOWN";
  }

  /**
   * @struct OMOrder
   * @brief 订单管理器使用的订单结构体
   * 
   * @details 订单管理器内部使用的结构体，用于表示单个策略订单。
   * 存储订单的关键信息，如证券ID、订单ID、侧向、价格、数量和状态。
   * 该结构体由订单管理器用来跟踪和管理策略发出的订单。
   */
  struct OMOrder {
    /**
     * @brief 证券标识符
     * 
     * @details 订单所对应的证券标识符，用于唯一标识订单所交易的证券。
     * 默认值为 TickerId_INVALID，表示无效证券ID。
     */
    TickerId ticker_id_ = TickerId_INVALID;
    
    /**
     * @brief 订单标识符
     * 
     * @details 唯一标识订单的标识符，用于跟踪和操作订单。
     * 默认值为 OrderId_INVALID，表示无效订单ID。
     */
    OrderId order_id_ = OrderId_INVALID;
    
    /**
     * @brief 订单侧向
     * 
     * @details 订单的交易方向，可以是买入（BUY）或卖出（SELL）。
     * 默认值为 Side::INVALID，表示无效侧向。
     */
    Side side_ = Side::INVALID;
    
    /**
     * @brief 订单价格
     * 
     * @details 订单的价格，用于确定订单在订单簿中的位置和成交条件。
     * 默认值为 Price_INVALID，表示无效价格。
     */
    Price price_ = Price_INVALID;
    
    /**
     * @brief 订单数量
     * 
     * @details 订单的数量，表示要买入或卖出的证券数量。
     * 默认值为 Qty_INVALID，表示无效数量。
     */
    Qty qty_ = Qty_INVALID;
    
    /**
     * @brief 订单状态
     * 
     * @details 订单的当前状态，表示订单在其生命周期中的位置。
     * 可能的状态包括无效、等待新建、活跃、等待取消和死亡。
     * 默认值为 OMOrderState::INVALID，表示无效状态。
     */
    OMOrderState order_state_ = OMOrderState::INVALID;

    /**
     * @brief 将订单转换为字符串表示
     * 
     * @details 生成订单的文本表示，包括证券ID、订单ID、侧向、价格、数量和状态。
     * 主要用于调试和日志记录。
     * 
     * @return 订单的字符串表示，格式为 "OMOrder[tid:xxx oid:xxx side:xxx price:xxx qty:xxx state:xxx]"
     */
    auto toString() const {
      std::stringstream ss;
      ss << "OMOrder" << "["
         << "tid:" << tickerIdToString(ticker_id_) << " "
         << "oid:" << orderIdToString(order_id_) << " "
         << "side:" << sideToString(side_) << " "
         << "price:" << priceToString(price_) << " "
         << "qty:" << qtyToString(qty_) << " "
         << "state:" << OMOrderStateToString(order_state_) << "]";

      return ss.str();
    }
  };

  /**
   * @typedef OMOrderSideHashMap
   * @brief 侧向到订单的映射
   * 
   * @details 使用固定大小的数组实现的哈希表，用于快速根据侧向（买入或卖出）查找对应的订单对象。
   * 数组大小由 sideToIndex(Side::MAX) + 1 决定，表示系统支持的最大侧向数量。
   */
  typedef std::array<OMOrder, sideToIndex(Side::MAX) + 1> OMOrderSideHashMap;

  /**
   * @typedef OMOrderTickerSideHashMap
   * @brief 证券ID和侧向到订单的二维映射
   * 
   * @details 使用固定大小的数组实现的二维哈希表，用于快速根据证券ID和侧向查找对应的订单对象。
   * 这是一个两级映射，首先根据证券ID查找对应的 OMOrderSideHashMap，然后再根据侧向查找对应的订单。
   * 数组大小由 ME_MAX_TICKERS 常量决定，表示系统支持的最大证券数量。
   */
  typedef std::array<OMOrderSideHashMap, ME_MAX_TICKERS> OMOrderTickerSideHashMap;
}
